/*
@Time : 2019/8/27 0027 14:50
@Author : visons
*/
package main

import (
	"fmt"
	"github.com/go-redis/redis"
)

/**
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的，所以添加，删除，查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
*/
func SortSetTest(client *redis.Client) {
	//ZAdd:向有序集合添加一个或多个成员，或者更新已存在成员的分数,分数值可以是整数值或双精度浮点数。
	//返回值:被成功添加的新成员的数量，不包括那些被更新的、已经存在的成员。
	effect, err := client.ZAdd("z1", redis.Z{17, "d"}).Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(effect)

	//计算集合中元素的数量。
	//返回值: 当 key 存在且是有序集类型时，返回有序集的基数。 当 key 不存在时，返回0
	length, err := client.ZCard("z1").Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(length)

	//Zcount 命令用于计算有序集合中指定分数区间的成员数量。
	length, err = client.ZCount("z1", "0", "10").Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(length)

	/**
	Zincrby 命令对有序集合中指定成员的分数加上增量 increment
	可以通过传递一个负数值 increment ，让分数减去相应的值，比如 ZINCRBY key -5 member ，就是让 member 的 score 值减去 5 。
	当 key 不存在，或分数不是 key 的成员时， ZINCRBY key increment member 等同于 ZADD key increment member 。
	当 key 不是有序集类型时，返回一个错误。
	分数值可以是整数值或双精度浮点数。
	*/
	//返回值：member 成员的新分数值，以字符串形式表示。
	score, err := client.ZIncrBy("z1", 2.0, "b").Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(score)

	//Zrange: 返回有序集中，指定区间内的成员,其中成员的位置按分数值递增(从小到大)来排序。
	//下标参数 start 和 stop 都以 0 为底，也就是说，以 0 表示有序集第一个成员，以 1 表示有序集第二个成员，以此类推。
	members, err := client.ZRange("z1", 0, 10).Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(members)

	//Zrevrange: 命令返回有序集中，指定区间内的成员,其中成员的位置按分数值递减(从大到小)来排列。
	//除了成员按分数值递减的次序排列这一点外， ZREVRANGE 命令的其他方面和 ZRANGE 命令一样。

	//Zrangebyscore: 返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大)次序排列。
	//具有相同分数值的成员按字典序来排列(该属性是有序集提供的，不需要额外的计算)。
	z, err := client.ZRangeWithScores("z1", 0, 100).Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(z)

	//Zrevrangebyscore: 返回有序集中指定分数区间内的所有的成员。有序集成员按分数值递减(从大到小)的次序排列。
	//除了成员按分数值递减的次序排列这一点外， ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE 命令一样

	//Zrank: 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。
	//返回值：如果成员是有序集 key 的成员，返回 member 的排名。 如果成员不是有序集 key 的成员，返回 nil 。
	rank, err := client.ZRank("z1", "b").Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(rank)

	//Redis Zrevrank 命令返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。
	//排名以 0 为底，也就是说， 分数值最大的成员排名为 0 。

	//Zrem 命令用于移除有序集中的一个或多个成员，不存在的成员将被忽略。
	effect, err = client.ZRem("z1", "z").Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(effect)

	//Zremrangebyrank 命令用于移除有序集中，指定排名(rank)区间内的所有成员。
	effect, err = client.ZRemRangeByRank("z1", 0, 1).Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(effect)

	//Zremrangebyscore 命令用于移除有序集中，指定分数（score）区间内的所有成员。
	effect, err = client.ZRemRangeByScore("z1", "11", "16").Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(effect)
}
